using System;
using System.Linq;
using Bots.DungeonBuddy.Helpers;
using CommonBehaviors.Actions;
using FarmerJoe.Helpers;
using FarmerJoe.Helpers.Logging;
using FarmerJoe.Helpers.Singular.Helpers;
using FarmerJoe.Helpers.Units;
using FarmerJoe.Settings;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace FarmerJoe.Classes
{
    public static partial class Druid
    {
        private static string _dpsSpell = "Wrath";
        private static string DPSSpell
        {
            get
            {
                if (StyxWoW.Me.HasAura("Eclipse (Solar)")) { _dpsSpell = "Wrath"; }
                else if (StyxWoW.Me.HasAura("Eclipse (Lunar)")) { _dpsSpell = "Starfire"; }

                return _dpsSpell;
            }
        }

        static int MushroomCount
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>().Where(o => o.Entry == 47649 && o.Distance <= 40).Count(o => o.CreatedByUnitGuid == StyxWoW.Me.Guid); }
        }

        static WoWUnit BestAoeTarget
        {
            get { return Clusters.GetBestUnitForCluster(AddsAndOthers.NearbyUnfriendlyUnits.Where(u => u.Combat && !u.IsCrowdControlled()), Clusters.ClusterType.Radius, 8f); }
        }


        public static Composite AstralCommunion()
        {
            return
                new Action(ret =>
                               {
                                   const string spellName = "Astral Communion";

                                   Logger.Write("=== AC 0.5");
                                   if (SpellManager.GlobalCooldown) return RunStatus.Success;
                                   Logger.Write("=== AC 1");
                                   if (Me.IsCasting || Me.IsChanneling) return RunStatus.Success;
                                   Logger.Write("=== AC 1.5");
                                   if (!SpellManager.HasSpell(spellName)) return RunStatus.Failure;
                                   //if (SpellManager.Spells[spellName].Cooldown) return RunStatus.Failure;
                                   //if (Me.IsCasting || Me.IsChanneling) return RunStatus.Success;

                                   Logger.Write("=== AC 2");
                                   //Logger.Write("=== AC 2 Ec Sol " + Me.HasAura("Eclipse (Solar)"));
                                   //Logger.Write("=== AC 2 Ec Lun " + Me.ActiveAuras.ContainsKey("Eclipse (Lunar)")); //.HasAura("Eclipse (Lunar)"));

                                   if (Me.ActiveAuras.ContainsKey("Eclipse (Solar)") || Me.ActiveAuras.ContainsKey("Eclipse (Lunar)")) return RunStatus.Failure;

                                   Logger.Write("=== AC 3");
                                   bool result = SpellManager.Cast(spellName);
                                   return result ? RunStatus.Success : RunStatus.Failure;
                               });
        }
        

        public static Composite CombatBehavior_Balance
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),

                    // Bear Form if we need to
                    new Decorator(ret => Me.ManaPercent < FpswareSettings.Instance.Druid.BalanceCatFormMana && Me.Shapeshift != ShapeshiftForm.Cat, CombatBehavior_Feral),
                    new Decorator(ret => Me.Shapeshift == ShapeshiftForm.Cat && Me.ManaPercent < (FpswareSettings.Instance.Druid.BalanceCatFormMana *1.5), CombatBehavior_Feral),

                    // Healing
                    //new Common.NeedToUseLifeSpirit(new Common.UseLifeSpirit()),
                    Common.UseHealthManaRegenAgent(ClassParser.HealthPotion, ClassParser.ManaPotion),
                    
                    AllFormsHeal(),

                    Inventory.UseTrinket1(),
                    Inventory.UseTrinket2(),

                    Spells.BuffSelf("Moonkin Form", ret => Me.Shapeshift != ShapeshiftForm.Moonkin),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    Movement.Fixes(),


                    Spells.Cast("Mighty Bash", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.BalanceMightyBash) && CT.IsWithinMeleeRange),
                    Spells.CastOnGround("Force of Nature", ret => CT.Location, ret => CLC.ResultOK(FpswareSettings.Instance.Druid.BalanceTrents)),


                    Spells.Cast("Wild Mushroom: Detonate", ret => !FpswareSettings.Instance.Druid.WildMushrooms.Contains("never") && MushroomCount >= Convert.ToInt32(FpswareSettings.Instance.Druid.WildMushroomMinDetonate) && CT.HostileUnitsNearTarget(10).Count() > Convert.ToInt32(FpswareSettings.Instance.Druid.WildMushroomMinMobs)),
                    Spells.CastOnGround("Wild Mushroom",
                            ret => BestAoeTarget.Location,
                            ret =>!FpswareSettings.Instance.Druid.WildMushrooms.Contains("never") && BestAoeTarget != null && SpellManager.HasSpell("Wild Mushroom") &&  (!SpellManager.Spells["Wild Mushroom: Detonate"].Cooldown || SpellManager.Spells["Wild Mushroom: Detonate"].CooldownTimeLeft.TotalSeconds <= 5)),

                    // Combat
                    // Trying to fix the not facing target issue
                    new Decorator(ret => !Me.IsMoving && !Me.Mounted && FpswareSettings.Instance.Druid.CCControlledMovement.Contains("always") && Me.GotTarget && !Me.IsSafelyFacing(CT,45),
                        new Action(context => CT.Face())),

                    Spells.Cast("Starsurge"),
                    Spells.Cast("Celestial Alignment", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.CelestialAlignment)),

                    Spells.CastOnGround("Hurricane", ret => CT.Location, ret => CLC.CountOfMobs(FpswareSettings.Instance.Druid.Hurricane, 8)),

                    Spells.Cast("Solar Beam", ret => CT.IsCasting && CT.CastingSpell.CastTime > 1500 && CLC.ResultOK(FpswareSettings.Instance.Druid.SolarBeam)),
                    Spells.Cast("Typhoon", ret => CT.DistanceSqr < 30*30 && CLC.ResultOK(FpswareSettings.Instance.Druid.Typhoon)),
                    Spells.Cast("Starfall", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.Starfall)),
                    Spells.Cast("Incarnation", ret => CLC.ResultOK(FpswareSettings.Instance.Druid.Incarnation)),
                    Spells.Cast("Faerie Fire", ret => (CT.AuraTimeLeft("Faerie Fire") < 3 && CT.AuraTimeLeft("Faerie Swarm") < 3) && CLC.ResultOK(FpswareSettings.Instance.Druid.FaerieFire)),
                    Spells.Cast("Sunfire", ret => (CT.AuraTimeLeft("Sunfire") < 3) && CLC.ResultOK(FpswareSettings.Instance.Druid.Sunfire)),
                    Spells.Cast("Moonfire", ret => ((CT.AuraTimeLeft("Moonfire") < 3) || Me.IsMoving) && CLC.ResultOK(FpswareSettings.Instance.Druid.Moonfire)),

                    Spells.Cast("Wrath", ret => DPSSpell == "Wrath"),
                    Spells.Cast("Starfire", ret => DPSSpell == "Starfire"),

                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),

                    Movement.MoveToTarget(true, 36f)
                    );
            }
        }

        public static Composite PullBehavior_Balance
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    new Sequence(ret => Me.Mounted, new Action(ret => Spells.Dismount("Pulling")), new Action(ctx => RunStatus.Failure)),

                    Spells.Cast("Moonkin Form", ret => Me.Shapeshift != ShapeshiftForm.Moonkin),

                    Movement.Fixes(),

                    //AstralCommunion(),

                    //Spells.Cast("Astral Communion", ret => FpswareSettings.Instance.Druid.AstralCommunion.Contains("always") && !Me.HasAura("Eclipse (Solar)") && !Me.HasAura("Eclipse (Lunar)")),

                    // User defined pull options
                    new Decorator(ret => FpswareSettings.Instance.Druid.BalancePull.Contains("user defined"),
                                  new PrioritySelector(
                                      Spells.Cast("Entangling Roots", ret => FpswareSettings.Instance.Druid.BalancePullEntanglingRoots.Contains("always") && !Me.IsMoving && !CT.HasAura("Entangling Roots") && !Me.IsCasting),//Timers.SpellOkToCast("Roots Pull", 2500)),
                                      Spells.Cast("Starsurge", ret => FpswareSettings.Instance.Druid.BalancePullStarsurge.Contains("always") && !Me.IsMoving),

                                      Spells.Cast("Starfire", ret => FpswareSettings.Instance.Druid.BalancePullStarfire.Contains("always") && !Me.IsMoving),
                                      Spells.Cast("Moonfire", ret => FpswareSettings.Instance.Druid.BalancePullMoonfire.Contains("always")),
                                      Spells.Cast("Wrath", ret => FpswareSettings.Instance.Druid.BalancePullWrath.Contains("always") && !Me.IsMoving)
                                      )),

                    // This is here because roots pulling is buggy as hell, we need something to trigger the combat routine when the pull target is rooted
                    new Decorator(ret => CT.HasAura("Entangling Roots"), CombatBehavior_Balance),

                    // Automatic fall through stuff
                    new Decorator(ret => FpswareSettings.Instance.Druid.BalancePull.Contains("automatic"),
                                  new PrioritySelector(
                                      Spells.Cast("Starsurge", ret => true),
                                      Spells.Cast("Starfire", ret => true),
                                      Spells.Cast("Moonfire", ret => true),
                                      Spells.Cast("Wrath", ret => true)
                                      )),


                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),

                    Movement.MoveToTarget(true, 35f)
                    );
            }
        }
        
    }
}